﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Foulds.Calculator.Service;
using Foulds.Calculator.StateMachine;

namespace Foulds.Calculator.UserInterface
{
    /// <summary>
    /// This partial class implements the logic for the calculator user interface.
    /// </summary>
    public partial class Calculator : Form
    {
        #region Member Variables
        /// <summary>The calculator service that will perform all the calculator logic.</summary>
        protected ICalculator CalculatorService;
        #endregion

        #region Constructor
        /// <summary>
        /// Initialize a new instance of the class.
        /// </summary>
        public Calculator()
        {
            InitializeComponent();

            // create the calcualtor service
            CreateCalculatorService();
        }
        #endregion
        
        #region Create Calculator Service
        /// <summary>
        /// Create and configure the calculator service that will be used in the back-end
        /// </summary>
        protected virtual void CreateCalculatorService()
        {
            this.CalculatorService = new Service.Calculator();
            this.CalculatorService.DisplayChanged += OnDisplayChanged;
        }
        #endregion
        
        #region Event Handlers

        #region On Shown
        /// <summary>
        /// Execute code when the form is shown for the first time.
        /// </summary>
        protected override void OnShown(EventArgs e)
        {
            base.OnShown(e);
            this.CalculatorService.PowerOn();
        }
        #endregion
        
        #region On Closing
        /// <summary>
        /// Execute code that should be run when the form is closed.
        /// </summary>
        protected override void OnClosing(CancelEventArgs e)
        {
            base.OnClosing(e);
            this.CalculatorService.PowerOff();
        } 
        #endregion
        
        #region Display Changed
        /// <summary>
        /// Handle the event that fires when the display should be updated.
        /// </summary>
        private void OnDisplayChanged(string inputDisplay, string expressionDisplay)
        {
            this.txtInput.Invoke(new MethodInvoker(delegate { this.txtInput.Text = inputDisplay; }));
            this.lblExpression.Invoke(new MethodInvoker(delegate { this.lblExpression.Text = expressionDisplay; }));
        }
        #endregion

        #region Calculator Key Click
        /// <summary>
        /// Handle the click events for all buttons
        /// </summary>
        private void CalculatorKeyClick(object sender, EventArgs e)
        {
            // get the calculator key tag
            Button button = (Button)sender;
            string keyTag = button.Tag as string;
            if (string.IsNullOrEmpty(keyTag))
                throw new ApplicationException("The button is not associated with a calculator key tag.");

            // get the calculator key name
            KeyName keyName = (KeyName)(Enum.Parse(typeof(KeyName), keyTag));

            // send the calculator key
            this.CalculatorService.PressKey(new CalculatorKey(keyName));
        }
        #endregion

        #endregion

    }
}
